package com.chang.common;


import com.jfinal.kit.PathKit;
import com.mongodb.*;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.Filters;
import com.mongodb.client.result.DeleteResult;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/********************************************************************************
 * 数据库驱动，用于对平台管理数据的管理
 * @author Dav
 * @version 2.0
 * @date 2020/6/1
 ********************************************************************************/
public class DataBase {
    private static String Host = null;
    private static String Port = null;
    private static String DataBaseName = null;
    private static String UserName = null;
    private static String Password = null;
    private static String MaxIdleTimeMS = null;
    private static MongoClient mongoClient = null;


    public DataBase() {
        if (mongoClient == null) {
            CreateClient();
        }
    }

    public static int getSequence(String Tag) {
        BasicDBObject FilterObject = new BasicDBObject().append("$and", new BasicDBObject[]{new BasicDBObject("_id", Tag)});
        List<Document> SequenceList = DataBase.find("sys_sequence", FilterObject, null);
        if (SequenceList == null || SequenceList.size() < 1) {
            // 不存在该序列，直接插入一个序列
            Document NewDocument = new Document();
            NewDocument.put("_id", Tag);
            NewDocument.put("sequence_value", Integer.parseInt("1"));
            DataBase.InsertNotAutoID("sys_sequence", NewDocument);
        }
        // 读出序列，并更新该序列
        SequenceList = DataBase.find("sys_sequence", FilterObject, null);
        int ReturnInt = SequenceList.get(0).getInteger("sequence_value");

        // 更新到库表
        int UpdateInt = ReturnInt + 1;
        Document UpdateDocument = new Document();
        UpdateDocument.put("sequence_value", UpdateInt);
        DataBase.updateByFilter("sys_sequence", FilterObject, UpdateDocument);
        return ReturnInt;
    }

    /***********************************************************************************
     * 通过WhereFilter更新
     * @param collName 集合名
     * @param filter 过滤器
     * @param newdoc 对象文档
     * @return
     ***********************************************************************************/
    public static Document updateByFilter(String collName, Bson WhereFilter, Document UpdateDoc) {
        try {
            if (mongoClient == null) {
                CreateClient();
            }
            if (null == collName || "".equals(collName)) {
                System.out.println("未找到目录");
                return null;
            }
            MongoCollection<Document> collection = mongoClient.getDatabase(DataBaseName).getCollection(collName);
            //***************************************************************************************************
            BasicDBObject update = new BasicDBObject("$set", UpdateDoc);
            collection.updateMany(WhereFilter, update);
            //***************************************************************************************************
            return UpdateDoc;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.toString());
            return null;
        }
    }

    public void destory() {
        mongoClient = null;
        System.gc();
    }
    /***************************************************************************************************
     * 读取自己的配置文件
     * @param ItemName
     * @return
     ***************************************************************************************************/
    private static String ReaderConfig(String ItemName) {
        try {
            String webRoot = PathKit.getWebRootPath();
            String ConfigPath = webRoot.concat(File.separator).concat("WEB-INF").concat(File.separator).concat("config.ini");
            ReaderINI ConfigReader = new ReaderINI(ConfigPath);
            String RetuanVal = ConfigReader.getValue("DataBase", ItemName);
            return RetuanVal;
        } catch (Exception Exp) {
            System.out.println("Platform.Common.Database:找不到数据库配置信息..........");
            return null;
        }
    }


    private static void CreateClient() {
        try {
            //*******************************************************
            Host = ReaderConfig("Host");
            Port = ReaderConfig("Port");
            DataBaseName = ReaderConfig("DataBaseName");
            UserName = ReaderConfig("UserName");
            Password = ReaderConfig("Password");
            MaxIdleTimeMS = ReaderConfig("MaxIdleTimeMS");
            //*******************************************************
            if (DataBaseName != null && !"".equals(DataBaseName)) {
                String MangoURL = String.format("mongodb://%s:%s@%s:%d/%s?maxIdleTimeMS=%s", UserName, Password, Host, Integer.parseInt(Port), DataBaseName, MaxIdleTimeMS);
                MongoClientURI MongoDBUrl = new MongoClientURI(MangoURL);
                ServerAddress serverAddress = new ServerAddress(Host, Integer.parseInt(Port));
                List<MongoCredential> credentialsList = new ArrayList<MongoCredential>();
                credentialsList.add(MongoCredential.createScramSha1Credential(UserName, DataBaseName, Password.toCharArray()));
                MongoClientOptions.Builder build = new MongoClientOptions.Builder();
                build.minConnectionsPerHost(10);
                build.connectionsPerHost(50);   // 与目标数据库能够建立的最大connection数量为50
                build.connectTimeout(1000 * 60 * 1);    // 与数据库建立连接的timeout设置为1分钟
                build.maxWaitTime(100 * 60 * 2); // 线程最大等待时间
                build.threadsAllowedToBlockForConnectionMultiplier(500); // 如果
                build.maxConnectionIdleTime(60000);
                build.maxConnectionLifeTime(0);
                build.socketTimeout(0);
                build.socketKeepAlive(true);
                MongoClientOptions myOptions = build.build();
                // 数据库连接实例
                mongoClient = new MongoClient(serverAddress, credentialsList, myOptions);
            }else {
                System.out.println("Platform.Common.Database:没有这个数据库.............");
            }
        } catch (Exception Exp) {
            System.out.println("Platform.Common.Database:创建数据库连接失败..........");
            System.out.println(Exp.toString());
        }
    }
    /***********************************************************************************
     * 插入文档
     * @param collName
     * @param InserObject
     ***********************************************************************************/
    public static Document InsertNotAutoID(String collName, Document InserObject) {
        try {
            if (mongoClient == null) {
                CreateClient();
            }
            if (null == collName || "".equals(collName)) {
                return null;
            }
            MongoCollection<Document> collection = mongoClient.getDatabase(DataBaseName).getCollection(collName);
            //****************************************************************************************************
            collection.insertOne(InserObject);
            return InserObject;
        } catch (Exception e) {
            System.out.println(e.toString());
            System.out.println(e.toString());
            return null;
        }
    }
    /***********************************************************************************
     * 插入文档
     * @param collName
     * @param InserObject
     ***********************************************************************************/
    public static Document Insert(String collName, Document InserObject) {
        try {
            if (mongoClient == null) {
                CreateClient();
            }
            if (null == collName || "".equals(collName)) {
                return null;
            }
            MongoCollection<Document> collection = mongoClient.getDatabase(DataBaseName).getCollection(collName);
            //****************************************************************************************************
            String Guid = UUID.randomUUID().toString();
            InserObject.put("_id", Guid);
            collection.insertOne(InserObject);
            return InserObject;
        } catch (Exception e) {
            System.out.println(e.toString());
            return null;
        }
    }
    /***********************************************************************************
     *   批量插入文档
     * @param collName
     * @param InserObject
     ***********************************************************************************/
    public static void Insert(String collName, List<Document> InserObject) {
        try {

            if (mongoClient == null) {
                CreateClient();
            }
            if (null == collName || "".equals(collName)) {
                return;
            }
            MongoCollection<Document> collection = mongoClient.getDatabase(DataBaseName).getCollection(collName);
            //****************************************************************************************************
            for (int i = 0; i < InserObject.size(); i++) {
                String Guid = UUID.randomUUID().toString();
                InserObject.get(i).put("_id", Guid);
            }
            collection.insertMany(InserObject);
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }

    /***********************************************************************************
     * 通过ID删除
     * @param collName 集合名
     * @param id 要删除的ID
     * @return
     ***********************************************************************************/
    public static int deleteById(String collName, String id) {
        if (mongoClient == null) {
            CreateClient();
        }
        if (null == collName || "".equals(collName)) {
            return -1;
        }
        MongoCollection<Document> collection = mongoClient.getDatabase(DataBaseName).getCollection(collName);

        int count = 0;
        ObjectId _id = null;
        try {
            _id = new ObjectId(id);
        } catch (Exception e) {
            return 0;
        }
        Bson filter = Filters.eq("_id", _id);
        DeleteResult deleteResult = collection.deleteOne(filter);
        count = (int) deleteResult.getDeletedCount();
        return count;
    }
    /***********************************************************************************
     * 通过ID更新
     * @param collName 集合名
     * @param id 要更新的ID
     * @param newdoc 对象文档
     * @return
     ***********************************************************************************/
    public static Document updateById(String collName, String id, Document newdoc) {
        if (mongoClient == null) {
            CreateClient();
        }
        if (null == collName || "".equals(collName)) {
            return null;
        }
        MongoCollection<Document> collection = mongoClient.getDatabase(DataBaseName).getCollection(collName);
        //***************************************************************************************************
        BasicDBObject WhereFilter = new BasicDBObject().append("$and", new BasicDBObject[]{new BasicDBObject("_id", id)});
        BasicDBObject update = new BasicDBObject("$set", newdoc);
        collection.updateMany(WhereFilter, update);
        return newdoc;
    }
    /**
     *条件查询
     * @param collName 集合名（表名）
     * @param filter 过滤条件
     * @param SortObject 排序
     * @return
     */
    public static List<Document> find(String collName, Bson filter, BasicDBObject SortObject) {
        if (mongoClient == null) {
            CreateClient();
        }
        if (null == collName || "".equals(collName)) {
            return null;
        }
        MongoCollection<Document> collection = mongoClient.getDatabase(DataBaseName).getCollection(collName);
        MongoCursor<Document> DocmentList = null;
        if (filter != null) {
            if (SortObject != null) {
                DocmentList = collection.find(filter).sort(SortObject).iterator();
            } else {
                DocmentList = collection.find(filter).iterator();
            }
        } else {
            if (SortObject != null) {
                DocmentList = collection.find().sort(SortObject).iterator();
            } else {
                DocmentList = collection.find().iterator();
            }
        }
        List<Document> _list = new ArrayList<Document>();
        int sys_tmp_order = 0;
        while (DocmentList.hasNext()) {
            org.bson.Document CureDocment = DocmentList.next();
            sys_tmp_order++;
            CureDocment.put("sys_tmp_order", sys_tmp_order);
            _list.add(CureDocment);
        }
        return _list;
    }
    public static List<Document> find(String collName, BasicDBObject SortObject) {
        if (mongoClient == null) {
            CreateClient();
        }
        if (null == collName || "".equals(collName)) {
            return null;
        }
        MongoCollection<Document> collection = mongoClient.getDatabase(DataBaseName).getCollection(collName);
        MongoCursor<Document> DocmentList = null;
        if (SortObject != null) {
            DocmentList = collection.find().sort(SortObject).iterator();
        } else {
            DocmentList = collection.find().iterator();
        }
        List<Document> _list = new ArrayList<Document>();
        int sys_tmp_order = 0;
        while (DocmentList.hasNext()) {
            org.bson.Document CureDocment = DocmentList.next();
            sys_tmp_order++;
            CureDocment.put("sys_tmp_order", sys_tmp_order);
            _list.add(CureDocment);
        }
        return _list;
    }


    /***********************************************************************************
     * 分页查询
     * @param collName 集合名
     * @param filter 过滤参数
     * @param pageNo 页码
     * @param pageSize 页大小
     * @return
     ***********************************************************************************/
    public static MongoCursor<Document> findByPage(String collName, Bson filter, int pageNo, int pageSize) {
        if (mongoClient == null) {
            CreateClient();
        }
        if (null == collName || "".equals(collName)) {
            return null;
        }
        MongoCollection<Document> collection = mongoClient.getDatabase(DataBaseName).getCollection(collName);
        Bson orderBy = new BasicDBObject("_id", 1);
        return collection.find(filter).sort(orderBy).skip((pageNo - 1) * pageSize).limit(pageSize).iterator();
    }

    /***********************************************************************************
     * 通过Filter删除
     * @param collName 集合名
     * @param filter 过滤器
     * @return
     ***********************************************************************************/
    public static int deleteByFilter(String collName, Bson filter) {
        if (mongoClient == null) {
            CreateClient();
        }
        if (null == collName || "".equals(collName)) {
            return -1;
        }
        MongoCollection<Document> collection = mongoClient.getDatabase(DataBaseName).getCollection(collName);
        int count = 0;
        DeleteResult deleteResult = collection.deleteMany(filter);
        count = (int) deleteResult.getDeletedCount();
        return count;
    }
}
